<template>
  <view>
    <mxp-page-loading v-if="newLoadState === true" :width="newEmptyWidth" :height="newEmptyHeight" text="袋鼠短剧"></mxp-page-loading>
    <scroll-view v-else-if="newLoadState === false" scroll-y :style="{ width: newEmptyWidth, height: `100vh` }" @scrolltolower="onReachBottom">
      <slot></slot>
      <mxp-load-more v-if="showMore" v-model="newLoadMoreState" :cusStyle="{ height: '40px' }" @loadmore="loadMoreClick"></mxp-load-more>
      <view v-if="newLoadMoreState === 'nomore'" key="view-2" :style="{ height: bottomPlaceholderHeight }"></view>
    </scroll-view>
    <view v-else style="display: flex; align-items: center; justify-content: center" :style="{ width: newEmptyWidth, height: newEmptyHeight }">
      <mxp-empty :img="newLoadState" :msg="msg" :style="{ width: newEmptyWidth }" :cusStyle="{ width: newEmptyWidth }">
        <mxp-button
          v-if="showButton"
          text="重新加载"
          radius="square"
          :plainBackground="false"
          size="middle"
          background="warning"
          :plain="true"
          :cusStyle="{ padding: '0px 30px', borderRadius: '30px' }"
          @click="retryQueryData"
        ></mxp-button>
      </mxp-empty>
    </view>
  </view>
</template>

<script setup lang="ts">
  import { type PropType, computed, nextTick, onMounted, ref, watch } from 'vue';
  import MxpPageLoading from '@/mxp-ui/mxp-page-loading/mxp-page-loading.vue';
  import MxpEmpty, { type EmptyState } from '@/mxp-ui/mxp-empty/mxp-empty.vue';
  import MxpLoadMore, { type LoadMoreState } from '@/mxp-ui/mxp-load-more/mxp-load-more.vue';
  import type { $AllSizeUnitStr } from '@/mxp-ui/mxp-tool/types/interface';
  import mxpGetSysInfoStore from '../mxp-tool/store/mxp-store-sys-info';
  import MxpButton from '../mxp-button/mxp-button.vue';

  export type LoadState = EmptyState | false | true;

  export type Ins = {
    /** 每一页的数据 */
    size: number;
    /** 第几页 */
    page: number;
    /**
     * 手动触发下拉刷新
     * 显示顶部的下拉刷新动画,如果不想显示顶部的加载动画,而是显示页面中间的加载中动画请调用initLoadRefresh()
     */
    startPullDownRefresh: () => void;

    /**
     * 显示页面加载中动画并刷新按钮
     * 显示页面中间的加载中的动画,如果不想显示中间的加载动画,而是显示顶部的下拉刷新动画,请调用startPullDownRefresh()
     */
    initLoadRefresh: (istPullDown?: boolean) => void;
    /** 停止下拉刷新 */
    stopPullDownRefresh: () => void;
    /**
     * 加载成功
     *注意: 用于仅仅使用下拉刷新的场景,如需同时使用上拉加载和下拉刷新请使用 setSuccessByList()
     */
    setSuccess: () => void;
    /**
     * 结束加载并设置为错误状态
     * 注意:如果需要使用上拉加载请使用 setEmptyByList()
     * @param type - 错误类型
     * @param msg - 错误提示
     * @param showButton - 是否显示按钮
     */
    setEmpty: (type: EmptyState, msg: string, showButton?: boolean) => void;

    /**
     * 隐藏下拉刷新和上拉加载的状态，且根据 list 判断是否显示空布局，用于上拉加载和下拉刷新都使用的场景
     * @param dataSize - 当前页获取的数据总数(注意是当前页)
     * @param totalSize - 列表的总数据量
     */
    setMoreSuccess: (dataSize: number, totalSize: number) => void;

    /**
     * 结束加载并设置为错误状态
     * 用于第一页加载失败时显示错误,非第一页时仅关闭上拉加载,不会显示错误页面
     * @param type - 错误类型
     * @param msg - 错误提示
     * @param showButton - 是否显示按钮
     */
    setMoreEmpty: (type: EmptyState, msg: string, showButton?: boolean) => void;
  };

  const props = defineProps({
    /** 错误或加载中组件的高度 */
    emptyHeight: { type: String as PropType<$AllSizeUnitStr>, default: undefined },
    /** 错误或加载中组件的宽度 */
    emptyWidth: { type: String as PropType<$AllSizeUnitStr>, default: undefined },
    /** 底部占位高度 (在加载结束后的占位高度) */
    bottomPlaceholderHeight: { type: String as PropType<$AllSizeUnitStr>, default: '40px' },
    /** 页面或下拉刷新状态 */
    loadState: { type: [String, Boolean] as PropType<LoadState>, default: true },
    /** 上拉加载状态 */
    loadMoreState: { type: [String] as PropType<LoadMoreState>, default: 'beforeLoad' },
    /** 最少有多少条数据才显示暂无更多 */
    showLoadMoreNumb: { type: Number, default: 40 },
    /** 每夜多少条数据 */
    pageSize: { type: Number, default: 40 },
    /** 首次是否自动加载数据 ,[注意]:如果设置为faise,但动态改变为true时会执行一次加载数据 */
    autoLaad: { type: Boolean, default: true },
    /** 请求方法 */
    queryData: { type: Function as PropType<(_ins: Ins) => Promise<any> | any>, default: undefined },
    /** 是否开启上拉加载 */
    reachBottom: { type: Boolean, default: false },
  });

  defineSlots<{
    /** 主体内容 */
    default: () => void;
  }>();

  const emits = defineEmits<{
    /** 页面加载状态发生改变 */
    (e: 'update:loadState', _loadState: LoadState): void;
    /** 上拉加载状态发生改变 */
    (e: 'update:loadMoreState', _loadMoreState: LoadMoreState): void;
  }>();

  const sys = mxpGetSysInfoStore().getSysInfo();
  const newEmptyWidth = computed(() => props.emptyWidth || `${sys.value.windowWidth}px`);
  const newEmptyHeight = computed(() => props.emptyHeight || `${sys.value.windowHeight - 60}px`);

  /** 总共有多少条数据 */
  const totalSize = ref(0);
  /** 已加载多少条数据 */
  const loadSize = ref(0);
  /** 下拉刷新加载状态 */
  const newLoadState = ref<LoadState>(props.loadState);
  /** 加载失败的消息 */
  const msg = ref<string>('加载失败');
  /** 上拉加载状态 */
  const newLoadMoreState = ref<LoadMoreState>(props.loadMoreState);
  /** 是否正在刷新 */
  const freshing = ref(false);
  /** 是否显示按钮 */
  const showButton = ref(true);

  watch(
    () => props.loadState,
    (state) => {
      newLoadState.value = state;
    }
  );

  watch(
    () => props.loadMoreState,
    (state) => {
      newLoadMoreState.value = state;
    }
  );

  watch(
    () => newLoadState.value,
    (state) => {
      emits('update:loadState', state);
    }
  );

  watch(
    () => newLoadMoreState.value,
    (state) => {
      emits('update:loadMoreState', state);
    }
  );

  watch(
    () => props.autoLaad,
    (state) => {
      state && retryQueryData();
    }
  );

  const showMore = computed(() => {
    if (props.reachBottom && newLoadState.value === false) {
      if (['nomore', 'beforeLoad'].includes(newLoadMoreState.value) && loadSize.value <= props.showLoadMoreNumb) {
        return false;
      } else {
        return true;
      }
    } else {
      return false;
    }
  });

  const ins: Ins = {
    size: (props?.pageSize as number) || 40,
    page: 1,
    startPullDownRefresh() {
      if (typeof props.queryData === 'function') {
        uni.startPullDownRefresh();
      }
    },
    initLoadRefresh() {
      if (typeof props.queryData === 'function') {
        props.queryData?.(ins);
      }
    },

    stopPullDownRefresh() {
      freshing.value = false;
      nextTick(() => {
        uni.stopPullDownRefresh();
      });
    },
    setSuccess() {
      freshing.value = false;
      newLoadState.value = false;
      nextTick(() => {
        uni.stopPullDownRefresh();
      });
    },

    setEmpty(type: EmptyState, _msg: string, _showButton = true) {
      freshing.value = false;
      showButton.value = _showButton;
      nextTick(() => {
        uni.stopPullDownRefresh();
      });
      newLoadState.value = type || 'fail_load';
      msg.value = _msg || '加载失败';
      newLoadMoreState.value = 'beforeLoad';
    },

    setMoreSuccess(dataSize: number, _totalSize: number) {
      totalSize.value = _totalSize;
      nextTick(() => {
        uni.stopPullDownRefresh();
      });
      freshing.value = false;
      loadSize.value += dataSize;
      if (ins.page <= 1) {
        if (dataSize <= 0) {
          // 如果是第一页且一条数据都没有
          ins.setEmpty('not_data', '暂无数据', false);
        } else {
          newLoadState.value = false;
          newLoadMoreState.value = _totalSize > loadSize.value ? 'beforeLoad' : 'nomore';
        }
      } else {
        newLoadState.value = false;
        newLoadMoreState.value = _totalSize > loadSize.value ? 'beforeLoad' : 'nomore';
      }
    },
    setMoreEmpty(type: EmptyState, _msg: string, _showButton = true) {
      freshing.value = false;
      showButton.value = _showButton;
      uni.stopPullDownRefresh();
      newLoadMoreState.value = 'beforeLoad';
      if (ins.page > 1) {
        newLoadState.value = type || 'fail_load';
        msg.value = _msg || '加载失败';
      }
    },
  };

  onMounted(() => {
    if (props.autoLaad && typeof props.queryData === 'function') {
      props.queryData?.(ins);
    }
  });

  /** 重新加载 */
  function retryQueryData() {
    if (!freshing.value && typeof props.queryData === 'function') {
      freshing.value = true;
      newLoadState.value = true;
      ins.page = 1;
      loadSize.value = 0;
      props.queryData?.(ins);
    }
  }

  /** 下拉刷新 */
  function onPullDownRefresh() {
    if (!freshing.value && typeof props.queryData === 'function') {
      freshing.value = true;
      ins.page = 1;
      loadSize.value = 0;
      props.queryData?.(ins);
    }
  }
  /** 点击加载更多 */
  function loadMoreClick() {
    onReachBottom();
  }

  /** 上拉加载 */
  function onReachBottom() {
    if (!freshing.value && loadSize.value < totalSize.value && typeof props.queryData === 'function') {
      ins.page++;
      freshing.value = true;
      newLoadMoreState.value = 'loading';
      props.queryData?.(ins);
    }
  }

  defineExpose({ ...ins, onPullDownRefresh, onReachBottom });
</script>
